package com.linln.modules.business.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.linln.common.data.MybatisPage;
import com.linln.component.shiro.ShiroUtil;
import com.linln.modules.business.dao.MapperAttendance;
import com.linln.modules.business.domain.Attendance;
import com.linln.modules.business.dto.AttendanceDTO;
import com.linln.modules.business.vo.LateReport;
import com.linln.modules.system.domain.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;


/**
 * @author Administrator
 */
@Service
public class AttendanceServiceImpl extends ServiceImpl<MapperAttendance, Attendance> {

    @Autowired
    private MapperAttendance mapperAttendance;

    /**
     * 查询个人打卡记录
     *
     * @return
     */
    public IPage<Attendance> getMyAttendances(Attendance attendance) {
        IPage<Attendance> iPage = MybatisPage.pageRequest();
        Long userId = ShiroUtil.getSubject().getId();
        QueryWrapper<Attendance> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        queryWrapper.orderBy(true, false, "record_time");

        return this.page(iPage, queryWrapper);
    }

    /**
     * 查询打卡记录
     *
     * @param attendance
     * @return
     */
    public IPage<Attendance> getAttendances(Attendance attendance) {
        IPage<Attendance> iPage = MybatisPage.pageRequest();

        QueryWrapper<Attendance> queryWrapper = new QueryWrapper<>();
        queryWrapper.between("record_time", attendance.getStartTime(), attendance.getEndTime());
        queryWrapper.orderBy(true, false, "record_time");
        return this.page(iPage, queryWrapper);
    }


    /**
     * 判断是否迟到
     *
     * @param now  打卡时间
     * @param type 打卡类型
     * @return
     */
    private boolean isLate(Date now, int type) {
        int hours = now.getHours();
        int minute = now.getMinutes();
        // 规定上午 8:00点后打卡为异常打卡,下班 17:00点之前打卡为异常
        //上班8：00后打卡
        if (type == 1 && (hours > 8 || (hours == 8 && minute >= 1))) {
            return true;
        } else
            //下班17:00点之前打卡
            if (type == 2 && (hours < 17)) {
                return true;
            } else {
                //正常打卡记录
                return false;
            }
    }

    /**
     * 个人打卡
     *
     * @param type 打卡类型 1 上班 2 下班
     * @return
     */
    public boolean punch(Integer type) {
        Attendance attendance = new Attendance();
        Date now = new Date();
        attendance.setRecordTime(now);
        if (isLate(now, type)) {
            attendance.setLate(1);
        } else {
            attendance.setLate(0);
        }
        User user = ShiroUtil.getSubject();
        //获取当前登录人ID
        attendance.setUserId(user.getId());
        attendance.setUserName(user.getNickname());
        attendance.setType(type);
        return this.save(attendance);
    }


    /**
     * 迟到统计 如果当天最晚上班打卡晚于8：00，则视为上班迟到。最晚下班打卡时间早于17：00，则视为下班提前跑路。
     *
     * @param recordDateStr 考勤年月份
     * @return
     */
    public List<LateReport> statLateReport(String recordDateStr) {
        List<AttendanceDTO> attendanceDTOS = mapperAttendance.statLateReport(recordDateStr);
        List<LateReport> lateReports = new ArrayList<>(64);
        Map<Long, LateReport> reportMap = new HashMap<>(64);
        //key 人员id+打卡日期+打卡类型 value 为true时 则表示当天对应打卡类型正常
        Map<String, Boolean> map = new HashMap(64);
        Set<Long> userIdSet = new HashSet<>(64);
        for (int i = 0; i < attendanceDTOS.size(); i++) {
            AttendanceDTO attendanceDTO = attendanceDTOS.get(i);
            StringBuilder builder = new StringBuilder();
            // key =>1 20101001 2
            Long userId = attendanceDTO.getUserId();

            if (!userIdSet.contains(userId)) {
                userIdSet.add(userId);
                LateReport lateReport = new LateReport();
                lateReport.setUserId(userId);
                lateReport.setLateTimes(0);
                lateReport.setUserName(attendanceDTO.getUserName());
                reportMap.put(userId, lateReport);
            }

            int type = attendanceDTO.getType();
            String key = builder.append(userId)
                    .append(attendanceDTO.getRecordTimeStr())
                    .append(attendanceDTO.getType()).toString();
            //是否当天第一次打卡并且类型一致
            boolean isFirst = false;
            if (!map.containsKey(key)) {
                map.put(key, false);
                isFirst = true;
            } else if (map.containsKey(key) && map.get(key)) {
                continue;
            }

            Date recordTime = attendanceDTO.getRecordTime();
            //判断打卡是否正常
            if (isLate(recordTime, type)) {
                map.put(key, false);
                //只记录当天第一次异常打卡并且打卡类型相同
                if (isFirst) {
                    LateReport lateReport = reportMap.get(userId);
                    Integer lateTimes = lateReport.getLateTimes();
                    lateTimes = lateTimes + 1;
                    lateReport.setLateTimes(lateTimes);
                    //加入打卡异常队列
                    lateReports.add(lateReport);
                }
            } else {
                map.put(key, true);
            }

        }
        return lateReports;
    }
}
